package com.link2room.aeriabots.facade.impl;

import com.link2room.aeriabots.constant.WXConstant;
import com.link2room.aeriabots.dto.param.inside.WxQrcodeInsideParamDto;
import com.link2room.aeriabots.dto.result.base.WxQrcodeResDto;
import com.link2room.aeriabots.facade.IQRCodeFacadeService;
import com.link2room.common.enums.BaseSysExceptionEnum;
import com.link2room.common.exception.SysException;
import com.link2room.common.jpa.result.QueryResult;
import com.link2room.common.service.ICommonService;
import com.link2room.common.util.ClassConverUtil;
import com.link2room.common.util.StringUtil;
import com.link2room.aeriabots.dto.result.api.WxReplyQrCodeDto;
import com.link2room.aeriabots.entity.WxCertificate;
import com.link2room.aeriabots.entity.WxQrcode;
import com.link2room.enums.exception.AeriabotsSysExceptionEnum;
import com.tencent.client.OfficialAccountClient;
import com.tencent.protocol.officialAccount.qrcode.create.QrcodeResDate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by LN on 2016/10/10.
 */
@Component("qrcodeFacadeService")
public class QRCodeFacadeServiceImpl extends BaseFacade implements IQRCodeFacadeService {
    @Resource
    protected ICommonService commonService;
    @Override
    public WxQrcodeResDto wxCreateQrcode(WxQrcodeInsideParamDto paramDto) throws Exception {
        String lhotelGroupCode = paramDto.getLhotelGroupCode();
        String type = paramDto.getType();
        String key = paramDto.getKey();

        if( StringUtil.isBlank(type)||StringUtil.isBlank(key)||StringUtil.isBlank(lhotelGroupCode)){
            throw new SysException(BaseSysExceptionEnum.INVALID_PARA.getCode(), BaseSysExceptionEnum.INVALID_PARA.getMsg()+" [type]:"+type+"\n[key]:"+key+"\n[lhotelGroupCpde]:"+"\n"+lhotelGroupCode, BaseSysExceptionEnum.INVALID_PARA.getBizType());
        }
        if(hasCreated(type,key,lhotelGroupCode)){
            throw new SysException(BaseSysExceptionEnum.INVALID_PARA.getCode(), AeriabotsSysExceptionEnum.WX_QRCODE_EXIST.getMsg()+" [type]:"+type+"\n[key]:"+key+"\n[lhotelGroupCpde]:"+"\n"+lhotelGroupCode, BaseSysExceptionEnum.INVALID_PARA.getBizType());
        }
        Integer sceneId = getWxSceneId().intValue();
        QrcodeResDate qrcodeRes = this.createQrcode(lhotelGroupCode,sceneId, paramDto.getScenStr());

        WxQrcodeResDto res = new WxQrcodeResDto();
        res.setTicket(qrcodeRes.getTicket());
        res.setUrl(qrcodeRes.getUrl());
        this.saveQrCode(lhotelGroupCode,paramDto.getLhotelCode(),sceneId,key,type,res);
        return res;
    }

    @Override
    public WxQrcodeResDto getQrcode(WxQrcodeInsideParamDto paramDto) throws Exception {
        String lhotelGroupCode = paramDto.getLhotelGroupCode();
        String type = paramDto.getType();
        String key = paramDto.getKey();

        if( StringUtil.isBlank(type)||StringUtil.isBlank(key)||StringUtil.isBlank(lhotelGroupCode)){
            throw new SysException(BaseSysExceptionEnum.INVALID_PARA.getCode(), BaseSysExceptionEnum.INVALID_PARA.getMsg()+" [type]:"+type+"\n[key]:"+key+"\n[lhotelGroupCpde]:"+"\n"+lhotelGroupCode, BaseSysExceptionEnum.INVALID_PARA.getBizType());
        }
        WxQrcode con = new WxQrcode();
        con.setLhotelGroupCode(lhotelGroupCode);
        con.setQrType(type);
        con.setQrkey(key);
        WxQrcode res = commonService.findOneEQ(WxQrcode.class, con);
        if(res == null){
            throw new SysException(BaseSysExceptionEnum.INVALID_PARA.getCode(), AeriabotsSysExceptionEnum.WX_QRCODE_NOT_EXIST.getMsg()+" [type]:"+type+"\n[key]:"+key+"\n[lhotelGroupCpde]:"+"\n"+lhotelGroupCode, BaseSysExceptionEnum.INVALID_PARA.getBizType());
        }
        WxQrcodeResDto resDto = new WxQrcodeResDto();
        resDto.setTicket(res.getTicket());
        resDto.setUrl(res.getUrl());
        return resDto;
    }

    @Override
    public QueryResult<WxReplyQrCodeDto> getWxReplyQrCodes(WxQrcodeInsideParamDto paramDto) throws Exception {
        String lhotelGroupCode = paramDto.getLhotelGroupCode();
        String type = WXConstant.WX_QRCODE.TYPE.REPLY;
        Integer currentPage = paramDto.getCurrentPage();
        Integer pageSize = paramDto.getPageSize();
        WxQrcode find = new WxQrcode();
        find.setQrType(type);
        find.setLhotelGroupCode(lhotelGroupCode);
        QueryResult<WxQrcode> queryRes = commonService.findAllEQ(WxQrcode.class, find, currentPage, pageSize);
        if(queryRes == null ||queryRes.getTotalrecord() == 0 || queryRes.getResultlist() == null){
            QueryResult res = new QueryResult();
            res.setTotalrecord(0);
            return res;
        }else{
            List<WxReplyQrCodeDto> list = queryRes.getResultlist().stream()
                    .map(qrcodeEntity -> ClassConverUtil.copyProperties(qrcodeEntity, WxReplyQrCodeDto.class))
                    .collect(Collectors.toList());
            QueryResult res = new QueryResult();
            res.setTotalrecord(queryRes.getTotalrecord());
            res.setResultlist(list);
            res.setCurrentPage(queryRes.getCurrentPage());
            return res;
        }
    }

    private boolean hasCreated(String type,String key,String lhotelGroupCode) throws Exception {
        WxQrcode wq = new WxQrcode();
        wq.setLhotelGroupCode(lhotelGroupCode);
        wq.setQrType(type);
        wq.setQrkey(key);
        long count = commonService.getCountAllEQ(WxQrcode.class, wq, null);
        if(count > 0){
            return true;
        }else{
            return false;
        }
    }
    private QrcodeResDate createQrcode(String hotelGroupCode,Integer sceneId,String sceneStr) throws Exception {
        WxCertificate wc = this.getWxCertificate(hotelGroupCode, null);
        QrcodeResDate res = OfficialAccountClient.qrcodeQRlimitCreate(wc.getAccessToken(),sceneId ,sceneStr);
        if(StringUtil.isNotBlank(res.getTicket())){
            return res;
        }else{
            throw new SysException(AeriabotsSysExceptionEnum.WX_SDK_ERROR.getCode(), AeriabotsSysExceptionEnum.WX_SDK_ERROR.getMsg()+"\n["+res.getErrcode()+"]:"+res.getErrmsg(), AeriabotsSysExceptionEnum.WX_SDK_ERROR.getBizType());
        }
    }

    /**
     * 生成场景id需要控制并发
     * @return
     * @throws Exception
     */
    private synchronized Long getWxSceneId() throws Exception {
        List<String> paramNames = new ArrayList<>();
        paramNames.add("WxQrcodeId");
        String idStr = commonService.findOneFieldByProcedure("create_No", paramNames);
//        SysNo sysNo = commonService.findOneById(SysNo.class,1L);
//        Long id = sysNo.getWxQrcodeId() + 1;
//        sysNo.setWxQrcodeId(id);
//        commonService.merge(sysNo);
        if(StringUtil.isNotBlank(idStr)&&StringUtil.isNumberString(idStr)){
            return new Long(idStr);
        }else{
            throw new SysException(AeriabotsSysExceptionEnum.WX_QRCODE_ID_GENERATE_ERROR);
        }
    }
    private void saveQrCode(String lhotelGroupCode,String hotelCode,Integer sceneId,String key ,String type ,WxQrcodeResDto res) throws Exception {
        //保存
        WxQrcode wq = new WxQrcode();
        wq.setLhotelGroupCode(lhotelGroupCode);
        wq.setTicket(res.getTicket());
        wq.setSceneId(sceneId);
        wq.setUrl(res.getUrl());
        long count = commonService.getCountAllEQ(WxQrcode.class, wq, null);
        if(count == 0){
            wq.setLhotelCode(hotelCode);
            wq.setQrkey(key);
            wq.setQrType(type);
            commonService.save(wq);
        }
    }
}
